package org.example.judge.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.example.judge.service.ProblemCaseService;
import org.example.judge.service.ProblemService;
import org.example.judge_common.annotation.AuthAnnotation;
import org.example.judge_common.entity.ResponseResult;
import org.example.judge_common.hander.RetrunMsgException;
import org.example.judge_common.properties.JudgeProperties;
import org.example.judge_common.util.IdWorker;
import org.example.judge_common.util.MyUtils;
import org.example.judge_pojo.Auth;
import org.example.judge_pojo.Problem;
import org.example.judge_pojo.ProblemCase;
import org.example.judge_pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

@Controller
@CrossOrigin
@Slf4j
@RequestMapping("/problem/case")

public class ProblemCaseController {
    @Qualifier("ProblemServiceImpl")
    @Autowired
    private ProblemService problemService;
    @Qualifier("ProblemCaseServiceImpl")
    @Autowired
    private ProblemCaseService problemCaseService;

    @Autowired
    private JudgeProperties judgeProperties;
    @Autowired
    private IdWorker idWorker;
    @RequestMapping("/save")
    @AuthAnnotation({"problem_case_save", Auth.ADMINISTRATOR})
    @ResponseBody
    public ResponseResult save(@RequestBody ProblemCase problemCase, HttpServletRequest request) throws RetrunMsgException {
        if(problemCase.getType()==0){ //数据样例
            if (problemCase.getInput().length()>1024||problemCase.getOutput().length()>1024) {
                throw new RetrunMsgException("测试数据超出限制:1024");
            }
        }
        //判断总数数量，一个题目最多十个测试数据
        int cases = problemCaseService.count(new QueryWrapper<ProblemCase>().eq("problem_id", problemCase.getProblemId()));
        if(cases>10){
            return ResponseResult.fail("数据数量超过限制");
        }
        if (problemCaseService.save(problemCase)) {
            return ResponseResult.success();
        }
        return ResponseResult.fail("测试用例上传失败");
    }

    /**
     * 上传测试文件文件
     * @param problemId
     * @param files files[0] 为输入数据，files【1】为输出数据
     * @param request
     * @return 返回生成的文件input_file_id = output_file_id = id
     * @throws RetrunMsgException
     */
    @PostMapping("/upload")
    @AuthAnnotation({"problem_case_upload",Auth.ADMINISTRATOR})
    @ResponseBody
    public ResponseResult upload(@RequestParam String problemId,@RequestParam("files") MultipartFile[] files, HttpServletRequest request) throws RetrunMsgException {


        if(files.length!=2|| MyUtils.isEmpty(problemId))return ResponseResult.fail("文件上传不符合要求");
//        System.out.println(problemId);
        File file = new File(judgeProperties.getDataDir(), problemId);
        if(!file.exists())file.mkdirs();
        String id = idWorker.nextId().toString();
        try {
            files[0].transferTo(new File(file,id+".in"));
            files[1].transferTo(new File(file,id+".out"));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RetrunMsgException("文件保存失败");
        }
        return ResponseResult.success().setData(id);
    }

    /**
     * 查看输入出入测试文件
     * @param problemId
     * @param fileId
     * @param response
     * @throws IOException
     */
    @RequestMapping("/download")
    @AuthAnnotation({Auth.ADMINISTRATOR})
    public void down(String problemId, String fileId, HttpServletResponse response) throws  IOException {
//        System.out.println(problemId);
        if( MyUtils.isEmpty(problemId)||MyUtils.isEmpty(fileId))return ;
        File file = new File(judgeProperties.getDataDir(), problemId);
//        String filename = fileId;
        //文件所在位置
        file = new File(file , fileId);
        ServletOutputStream outputStream = null;
        FileInputStream fileInputStream = null;

//        response.setHeader("content-type", "video/mp4");
        try{

            outputStream = response.getOutputStream();
            fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[1024];
            int read = 0;
            while ((read = fileInputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
        } catch (Exception e) {
            log.error("文件" + fileId + "读取失败: " + e.getMessage());
//            throw new RetrunMsgException("系统找不到指定文件");
            outputStream.write("系统找不到指定文件".getBytes("GBK"));
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    log.error("文件" + fileId + "输出流关闭失败: " + e.getMessage());
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("response.outputStream输出流关闭失败: " + e.getMessage());
                }
            }

        }
    }

    @DeleteMapping("/delete/{id}")
    @AuthAnnotation({"problem_case_delete",Auth.ADMINISTRATOR})
    @ResponseBody
    public ResponseResult deleteById(@PathVariable String id,HttpServletRequest request){
        ProblemCase byId = problemCaseService.getById(id);
        if(byId==null)return ResponseResult.fail("不存在该测试样例");
        if (byId.getType()==1) {//文件测试样例
            File file = new File(judgeProperties.getDataDir(), byId.getProblemId());
            File file1 = new File(file, id + ".in");
            //删除文件
            if(file1.exists())file1.delete();
            File file2 = new File(file, id + ".out");
            if(file2.exists())file2.delete();
        }
        problemCaseService.removeById(id);
        if (request != null) {
            User loginUser = (User) request.getAttribute("loginUser");
            log.info("用户{}删除了测试数据ID：{}",loginUser.getUsername(),id);
        }
        return ResponseResult.success();
    }
    @PutMapping("/update")
    @AuthAnnotation({"problem_case_update",Auth.ADMINISTRATOR})
    @ResponseBody
    public ResponseResult updateById(@RequestBody ProblemCase problemCase){
        problemCaseService.updateById(problemCase);
        return ResponseResult.success();
    }

    /**
     * 获取指定题目的所有测试用例
     * @param problemId
     * @return
     */
    @PostMapping("/list/{id}")
    @AuthAnnotation({"problem_case_list",Auth.ADMINISTRATOR})
    @ResponseBody
    public ResponseResult listByProblemId(@PathVariable("id")String problemId){
        List<ProblemCase> list = problemCaseService.listByProblemId(problemId);
        if(list==null||list.size()==0)return ResponseResult.NotData("还没有添加测试用例");
        return ResponseResult.success().setData(list);
    }
    /**
     * 获取指定题目的所有显示于题面example测试用例
     * @param problemId
     * @return
     */
    @PostMapping("/examples/{id}")
    @AuthAnnotation({"problem_case_list",Auth.CLIENT})
    @ResponseBody
    public ResponseResult listExampleByProblemId(@PathVariable("id")String problemId){
        Problem byId = problemService.getById(problemId);

        List<ProblemCase> list = problemCaseService.listExampleByProblemId(problemId);
        if(list==null||list.size()==0)return ResponseResult.NotData("无测试样例");
        return ResponseResult.success().setData(list);
    }
}
